﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using System.IO;
using System.Net;

namespace Rookey.Frame.IMClient
{
	public class Browser : WebBrowser
	{
		public Browser()
		{
			ObjectForScripting = new ClientCall(this);
		}

		[System.Runtime.InteropServices.ComVisibleAttribute(true)]
		public class ClientCall
		{
			Browser _browser = null;

			public ClientCall(Browser b)
			{
				_browser = b;
				_session = new SessionImpl(b);
			}

			public object CreateWindow(object config)
			{
				Window win = new Window();
				win.Init(config);
				return win.IWindow;
			}

			public void ShowError(string message)
			{
				MessageBox.Show(_browser, message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}

			public void ShowWarning(string message)
			{
				MessageBox.Show(_browser, message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
			}

			public String Version
			{
				get { return Assembly.GetExecutingAssembly().GetName().Version.ToString(); }
			}

			SessionImpl _session = null;

			public SessionImpl Session
			{
				get { return _session; }
			}

			public Window.IWindowImpl OutputPanel
			{
				get { return null; }
			}

			public object Desktop
			{
				get { return Global.Desktop.IWindow.GetHtmlWindow(); }
			}

			public String OpenFile(String filter)
			{
				OpenFileDialog ofd = new OpenFileDialog();
				ofd.Filter = filter;
				if (ofd.ShowDialog(_browser) == DialogResult.OK)
				{
					return ofd.FileName;
				}
				else
				{
					return String.Empty;
				}

			}

            public void ExitApplication()
            {
                Global.Desktop.Close();
                ReceiveResponseHandler.Global.Stop();
                Global.TrayIcon.Visible = false;
                Application.Exit();
            }

			public void RestartApplication()
			{
				Global.Desktop.Close();
				ReceiveResponseHandler.Global.Stop();
				Global.TrayIcon.Visible = false;
				System.Diagnostics.Process.Start(AppDomain.CurrentDomain.BaseDirectory + "Rookey.Frame.IMClient.exe");
				Application.Exit();
			}

			public String GradScreen()
			{
				int width = Screen.PrimaryScreen.Bounds.Width;
				int height = Screen.PrimaryScreen.Bounds.Height;
				Bitmap bmp = new Bitmap(width, height);
				using (Graphics g = Graphics.FromImage(bmp))
				{
					g.CopyFromScreen(0, 0, 0, 0, new Size(width, height));
				}
				FullScreenForm screen = new FullScreenForm(bmp);
				if (screen.ShowDialog() == DialogResult.OK)
				{
					string tempFile = String.Format(@"{0}\{1}.jpg", Path.GetTempPath(), Guid.NewGuid().ToString().Replace("-", ""));
					screen.ResultBitmap.Save(tempFile, System.Drawing.Imaging.ImageFormat.Jpeg);
					return tempFile;
				}
				else
				{
					return String.Empty;
				}
			}

			public String ToBase64String(String file)
			{
				Byte[] buffer = File.ReadAllBytes(Microsoft.JScript.GlobalObject.unescape(file));
				return Convert.ToBase64String(buffer);
			}

			public void Open(string cookie, string url, string name, object handler)
			{
				String dir = String.Format(@"{0}{1}", Path.GetTempPath(), Guid.NewGuid().ToString().Replace("-", ""));
				Directory.CreateDirectory(dir);

				OpenFileHandler dl = new OpenFileHandler(cookie, url, dir + "\\" + name, _browser, handler);
				dl.Download();
			}

			public void Upload(string cookie, string file, object handler)
			{
				UploadFileHandler dl = new UploadFileHandler(cookie, Global.ServiceUrl + "/sendfile.aspx", file, _browser, handler);
				dl.Upload();
			}


			public void Save(string cookie, string url, string name, object handler)
			{
				SaveFileDialog sfd = new SaveFileDialog();
				sfd.FileName = name;
				if (sfd.ShowDialog(_browser) == DialogResult.OK)
				{
					SaveFileHandler dl = new SaveFileHandler(cookie, url, sfd.FileName, _browser, handler);
					dl.Download();
				}
			}

			private class OpenFileHandler
			{
				string _url, _local, _cookie;
				Browser _borwser;
				object _handler;
				WebClient _client;

				long _recvBytes = 0;
				long _ticks = 0;

				public OpenFileHandler(string cookie, string url, string local, Browser browser, object handle)
				{
					_url = Config.Instance.ServiceUrl + "/" + url;
					_borwser = browser;
					_local = local;
					_handler = handle;
					_cookie = cookie;
				}

				public void Download()
				{
					_borwser.BeginInvoke(new HandlerBeforeDownloadDelegate(HandlerBeforeDownload));

					try
					{
						_client = new WebClient();
						_client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
						_client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
						_client.Headers.Add("Cookie", _cookie);

						_ticks = DateTime.Now.Ticks;

						_client.DownloadFileAsync(new Uri(_url), _local);
					}
					catch (Exception e)
					{
						_borwser.BeginInvoke(new HandlerErrorDelegate(HandlerError), e.Message);
						return;
					}
				}

				void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
				{
					try
					{
						_borwser.BeginInvoke(new HandlerProcessingDelegate(HandlerProcessing), (int)e.BytesReceived, (int)e.TotalBytesToReceive);
					}
					catch
					{
						_client.CancelAsync();
					}
				}

				void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
				{
					try
					{
						if (e.Error == null) _borwser.BeginInvoke(new HandlerAfterDownloadDelegate(HandlerAfterDownload), e.Cancelled);
						else _borwser.BeginInvoke(new HandlerErrorDelegate(HandlerError), e.Error.Message);
					}
					catch
					{
					}
				}

				delegate void HandlerBeforeDownloadDelegate();
				void HandlerBeforeDownload()
				{
					_handler.GetType().InvokeMember("BeforeDownload", BindingFlags.InvokeMethod, null, _handler, new object[] { });
				}

				delegate void HandlerProcessingDelegate(long length, long size);
				void HandlerProcessing(long length, long size)
				{
					long temp = DateTime.Now.Ticks - _ticks;
					if (temp > 10000 * 1000 || length == size)
					{
						int ret = (int)_handler.GetType().InvokeMember("Processing", BindingFlags.InvokeMethod, null, _handler, new object[] { (int)length, (int)size, temp == 0 ? 0 : (int)((length - _recvBytes) * 1000 / (temp / 10000)) });
						if (ret == 0) _client.CancelAsync();
						_ticks += temp;
						_recvBytes = length;
					}
				}

				delegate void HandlerAfterDownloadDelegate(bool canceled);
				void HandlerAfterDownload(bool canceled)
				{
					if (!canceled)
					{
						System.Diagnostics.ProcessStartInfo psf = new System.Diagnostics.ProcessStartInfo();
						psf.FileName = _local;
						psf.Verb = "open";
						System.Diagnostics.Process.Start(psf);
					}
					_handler.GetType().InvokeMember("AfterDownload", BindingFlags.InvokeMethod, null, _handler, new object[] { });
				}

				delegate void HandlerErrorDelegate(string msg);
				void HandlerError(string msg)
				{
					_handler.GetType().InvokeMember("HandleError", BindingFlags.InvokeMethod, null, _handler, new object[] { msg });
				}

			}

			private class SaveFileHandler
			{
				string _url, _local, _cookie;
				Browser _borwser;
				object _handler;
				WebClient _client;

				long _recvBytes = 0;
				long _ticks = 0;

				public SaveFileHandler(string cookie, string url, string local, Browser browser, object handle)
				{
					_url = Config.Instance.ServiceUrl + "/" + url;
					_borwser = browser;
					_local = local;
					_handler = handle;
					_cookie = cookie;
				}

				public void Download()
				{
					_borwser.BeginInvoke(new HandlerBeforeDownloadDelegate(HandlerBeforeDownload));

					try
					{
						_client = new WebClient();
						_client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
						_client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
						_client.Headers.Add("Cookie", _cookie);

						_ticks = DateTime.Now.Ticks;

						_client.DownloadFileAsync(new Uri(_url), _local);
					}
					catch (Exception e)
					{
						_borwser.BeginInvoke(new HandlerErrorDelegate(HandlerError), e.Message);
						return;
					}
				}

				void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
				{
					try
					{
						_borwser.BeginInvoke(new HandlerProcessingDelegate(HandlerProcessing), (int)e.BytesReceived, (int)e.TotalBytesToReceive);
					}
					catch
					{
						_client.CancelAsync();
					}
				}

				void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
				{
					try
					{
						if (e.Error == null) _borwser.BeginInvoke(new HandlerAfterDownloadDelegate(HandlerAfterDownload), e.Cancelled);
						else _borwser.BeginInvoke(new HandlerErrorDelegate(HandlerError), e.Error.Message);
					}
					catch
					{
						_client.CancelAsync();
					}
				}

				delegate void HandlerBeforeDownloadDelegate();
				void HandlerBeforeDownload()
				{
					_handler.GetType().InvokeMember("BeforeDownload", BindingFlags.InvokeMethod, null, _handler, new object[] { });
				}

				delegate void HandlerProcessingDelegate(long length, long size);
				void HandlerProcessing(long length, long size)
				{
					long temp = DateTime.Now.Ticks - _ticks;
					if (temp > 10000 * 1000 || length == size)
					{
						int ret = (int)_handler.GetType().InvokeMember("Processing", BindingFlags.InvokeMethod, null, _handler, new object[] { (int)length, (int)size, temp == 0 ? 0 : (int)((length - _recvBytes) * 1000 / (temp / 10000)) });
						if (ret == 0) _client.CancelAsync();
						_ticks += temp;
						_recvBytes = length;
					}
				}

				delegate void HandlerAfterDownloadDelegate(bool canceled);
				void HandlerAfterDownload(bool canceled)
				{
					_handler.GetType().InvokeMember("AfterDownload", BindingFlags.InvokeMethod, null, _handler, new object[] { });
				}

				delegate void HandlerErrorDelegate(string msg);
				void HandlerError(string msg)
				{
					_handler.GetType().InvokeMember("HandleError", BindingFlags.InvokeMethod, null, _handler, new object[] { msg });
				}

			}

			private class UploadFileHandler
			{
				string _url, _local, _cookie;
				Browser _borwser;
				object _handler;
				WebClient _client;

				long _recvBytes = 0;
				long _ticks = 0;

				public UploadFileHandler(string cookie, string url, string local, Browser browser, object handle)
				{
					_url = url;
					_borwser = browser;
					_local = local;
					_handler = handle;
					_cookie = cookie;
				}

				public void Upload()
				{
					_borwser.BeginInvoke(new HandlerBeforeUploadDelegate(HandlerBeforeUpload));

					try
					{
						_client = new WebClient();
						_client.UploadFileCompleted += new UploadFileCompletedEventHandler(client_UploadFileCompleted);
						_client.UploadProgressChanged += new UploadProgressChangedEventHandler(client_UploadProgressChanged);
						_client.Headers.Add("Cookie", _cookie);

						_ticks = DateTime.Now.Ticks;

						_client.UploadFileAsync(new Uri(_url), "POST", _local);
					}
					catch (Exception e)
					{
						_borwser.BeginInvoke(new HandlerErrorDelegate(HandlerError), e.Message);
						return;
					}
				}

				void client_UploadProgressChanged(object sender, UploadProgressChangedEventArgs e)
				{
					try
					{
						_borwser.BeginInvoke(new HandlerProcessingDelegate(HandlerProcessing), (int)e.BytesSent, (int)e.TotalBytesToSend);
					}
					catch
					{
						_client.CancelAsync();
					}
				}

				void client_UploadFileCompleted(object sender, UploadFileCompletedEventArgs e)
				{
					try
					{
						if (e.Error == null)
						{
							String content = Encoding.UTF8.GetString(e.Result);
							Hashtable data = Utility.ParseJson(content) as Hashtable;
							if ((bool)data["Result"])
							{
								_borwser.BeginInvoke(new HandlerAfterUploadDelegate(HandlerAfterUpload), e.Cancelled, data["Path"]);
							}
							else
							{
								Exception ex = data["Exception"] as Exception;
								_borwser.BeginInvoke(new HandlerErrorDelegate(HandlerError), ex.Message);
							}
						}
						else
						{
							_borwser.BeginInvoke(new HandlerErrorDelegate(HandlerError), e.Error.Message);
						}
					}
					catch
					{
					}
				}

				delegate void HandlerBeforeUploadDelegate();
				void HandlerBeforeUpload()
				{
					_handler.GetType().InvokeMember("BeforeUpload", BindingFlags.InvokeMethod, null, _handler, new object[] { });
				}

				delegate void HandlerProcessingDelegate(long length, long size);
				void HandlerProcessing(long length, long size)
				{
					long temp = DateTime.Now.Ticks - _ticks;
					if (temp > 10000 * 1000 || length == size)
					{
						int ret = (int)_handler.GetType().InvokeMember("Processing", BindingFlags.InvokeMethod, null, _handler, new object[] { (int)length, (int)size, temp == 0 ? 0 : (int)((length - _recvBytes) * 1000 / (temp / 10000)) });
						if (ret == 0) _client.CancelAsync();
						_ticks += temp;
						_recvBytes = length;
					}
				}

				delegate void HandlerAfterUploadDelegate(bool canceled, string path);
				void HandlerAfterUpload(bool canceled, string path)
				{
					_handler.GetType().InvokeMember("AfterUpload", BindingFlags.InvokeMethod, null, _handler, new object[] { path });
				}

				delegate void HandlerErrorDelegate(string msg);
				void HandlerError(string msg)
				{
					_handler.GetType().InvokeMember("HandleError", BindingFlags.InvokeMethod, null, _handler, new object[] { msg });
				}

			}
		}
	}
}
